package org.oschina.api.dongtan.service;

import java.util.List;
import org.oschina.Config;
import org.oschina.Constants;
import org.oschina.Message;
import org.oschina.Module;
import org.oschina.ResultUtil;
import org.oschina.api.BaseService;
import org.oschina.api.comment.CommentCatalog;
import org.oschina.api.comment.model.Comment;
import org.oschina.api.comment.service.CommentService;
import org.oschina.api.dongtan.DongtanType;
import org.oschina.api.dongtan.dao.DongtanDAO;
import org.oschina.api.dongtan.model.Dongtan;
import org.oschina.api.dongtan.model.DongtanComment;
import org.oschina.api.dongtan.vo.DongtanAccessVo;
import org.oschina.api.dongtan.vo.DongtanVo;
import org.oschina.api.manage.config.service.ConfigService;
import org.oschina.api.manage.module.ModuleType;
import org.oschina.api.manage.module.vo.ModuleVo;
import org.oschina.api.user.active.UserActiveType;
import org.oschina.api.user.active.service.UserActiveService;
import org.oschina.api.user.role.service.UserRoleService;
import org.oschina.api.user.user.model.User;
import org.oschina.api.user.user.service.UserService;
import org.oschina.api.user.user.vo.UserVo;
import org.oschina.bean.Pager;
import org.oschina.bean.Result;
import org.oschina.plugin.PluginHelper;
import org.oschina.plugin.PluginType;
import org.oschina.api.index.service.IndexService;
import org.oschina.security.AuthenticationException;
import org.oschina.security.ISecurity;
import org.oschina.security.annotation.Require;
import org.oschina.util.DateUtil;
import org.oschina.util.ListUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DongtanService extends BaseService {

	@Autowired
	private DongtanDAO dongtanDAO;
	@Autowired
	private UserService userService;
	@Autowired
	private PluginHelper pluginHelper;
	@Autowired
	private CommentService commentService;
	@Autowired
	private IndexService indexService;
	@Autowired
	private ConfigService configService;
	@Autowired
	private ISecurity security;
	@Autowired
	private UserRoleService roleService;
	@Autowired
	private UserActiveService userActiveService;

	/**
	 * 恢复已删除
	 * @param id
	 * @return
	 */
	@Require(authorization=Module.MODULE_34)
	public Result recoverDelete(int id)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isDelete(dongtanVo))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		_updateType(dongtanVo, DongtanType.SIMPLE);
		return ResultUtil.getSuccess(Message.UPDATE_SUCCESS);
	}
	
	/**
	 * 返回已删除
	 * @param pn
	 * @return
	 */
	@Require(authorization=Module.MODULE_34)
	public Pager<DongtanVo> findDelete(int pn)
	{
		Pager<DongtanVo> pager=new Pager(pn,_getCountByType(DongtanType.DELETE),_getPageCount(),null);
		if(pager.getData_sum()>0)
			pager.setData(_findVoByType(DongtanType.DELETE, pager.getStart(), pager.getPage_count()));
		
		return pager;
	}
		
	/**
	 * 删除
	 * @param id
	 * @return
	 */
	public Result delete(int id)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isSimple(dongtanVo))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		_require(getToken(), dongtanVo, new String[]{Module.MODULE_33}, new String[]{Module.MODULE_32});
		_setDelete(dongtanVo);
		return ResultUtil.getSuccess(Message.DELETE_SUCCESS);
	}
	
	/**
	 * 编辑
	 * @param id
	 * @param content
	 * @return
	 */
	public Result edit(int id,String content)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isSimple(dongtanVo))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		_require(getToken(), dongtanVo, new String[]{Module.MODULE_31}, new String[]{Module.MODULE_30});
		
		_edit(id,content);
		return ResultUtil.getSuccess(Message.UPDATE_SUCCESS);
	}
	
	/**
	 * 发表评论
	 * @param dongtan_id
	 * @param content
	 * @param quote
	 * @return
	 */
	@Require
	public Result createComment(int dongtan_id,String content,int quote)
	{
		DongtanVo dongtan=_findVoById(dongtan_id);
		
		if(dongtan==null || !_isSimple(dongtan))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		DongtanComment dongtanComment=new DongtanComment(getToken(),dongtan,content);
		pluginHelper.execute(PluginType.DONGTAN_COMMENT_CREATE_BEFORE, dongtanComment);
		Result result=commentService._create(dongtan.getId(), dongtanComment.getDongtanVo().getComment_id(), dongtanComment.getContent(), quote,CommentCatalog.DONGTAN);
		
		if(result.isSuccess())
		{
			_updateCommentCount_plus(dongtan);
			dongtanComment.setComment((Comment)result.getMessage());
			pluginHelper.execute(PluginType.DONGTAN_COMMENT_CREATE_AFTER, dongtanComment);
			userActiveService.create(dongtan_id, dongtan.getContent(), content, UserActiveType.DONGTAN_COMMENT);
		}
		
		return result;
	}
	
	/**
	 * 根据ID返回
	 * @param id
	 * @return
	 */
	public DongtanAccessVo findById(int id)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isSimple(dongtanVo))
			return null;
		
		_updateViewsCount_plus(dongtanVo);
		
		DongtanAccessVo dongtanAccessVo=new DongtanAccessVo();
		dongtanAccessVo.setDongtan(dongtanVo);
		
		User user=userService.getAuthenticationInfo(getToken());
		if(user!=null)
		{
			List<ModuleVo> module=roleService._findVoByRoleAndType(user, ModuleType.MODULE_13);
			if(_isAuthor(dongtanVo, user))
			{
				module.addAll(roleService._findVoByRoleAndType(user, ModuleType.MODULE_12));
				module=ListUtil.removeRepeat(module);
			}
			dongtanAccessVo.setModule(module);
		}
		
		return dongtanAccessVo;
	}
	
	/**
	 * 发动弹
	 * @param dongtan
	 * @return
	 */
	@Require(authorization=Module.MODULE_7)
	public Result create(Dongtan dongtan)
	{
		dongtan=_create(dongtan,userService.getVo(getToken()),getIp());
		userActiveService.create(dongtan.getId(), dongtan.getContent(), null, UserActiveType.DONGTAN);
		return ResultUtil.getSuccess(dongtan);
	}
	
	/**
	 * 查询最热
	 * @param pn
	 * @return
	 */
	public Pager<DongtanVo> findVoByHot(int pn)
	{
		Pager pager=new Pager(1,_getPageCount(),_getPageCount(),null);
		pager.setData(_findVoByHot(pager.getStart(), pager.getPage_count()));
		return pager;
	}
	
	/**
	 * 查询最热
	 * @return
	 */
	public Pager<DongtanVo> findVoByHot()
	{
		return new Pager(1,_getHotCount(),_getHotCount(),_findVoByHot(0,_getHotCount()));
	}
	
	/**
	 * 查询最新
	 * @return
	 */
	public Pager<DongtanVo> findVoByUpToDate()
	{
		return new Pager(1,_getToUpDateCount(),_getToUpDateCount(),_findVoByUpToDate(0,_getToUpDateCount()));
	}
	
	/**
	 * 查询最新
	 * @param pn
	 * @return
	 */
	public Pager<DongtanVo> findVoByUpToDate(int pn)
	{
		Pager pager=new Pager(pn,_getPageCount(),_getPageCount(),null);
		pager.setData(_findVoByUpToDate(pager.getStart(), pager.getPage_count()));
		return pager;
	}
	
	/**
	 * 删除评论
	 * @param id
	 * @return
	 */
	public void _deleteComment(int id)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isSimple(dongtanVo))
			return;
		
		_updateCommentCount_minus(dongtanVo);
	}
	
	/**
	 * 举报评论
	 * @param id
	 */
	public void _reportComment(int id)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isSimple(dongtanVo))
			return;
		
		_updateCommentCount_minus(dongtanVo);
	}
	
	/**
	 * 恢复评论
	 * @param id
	 */
	public void _recoverComment(int id)
	{
		DongtanVo dongtanVo=_findVoById(id);
		if(dongtanVo==null || !_isSimple(dongtanVo))
			return;
		
		_updateCommentCount_plus(dongtanVo);
	}
	
	/**
	 * 根据类型返回
	 * @param type
	 * @param first
	 * @param max
	 * @return
	 */
	private List<DongtanVo> _findVoByType(int type,int first,int max)
	{
		return dongtanDAO.findVoByType(type, first, max);
	}
	
	/**
	 * 根据类型返回数量
	 * @param type
	 * @return
	 */
	private int _getCountByType(int type)
	{
		return dongtanDAO.getCountByType(type);
	}
	
	/**
	 * 根据ID返回
	 * @param id
	 * @return
	 */
	private DongtanVo _findVoById(int id)
	{
		return dongtanDAO.findVoById(id);
	}
	
	/**
	 * 查询最热
	 * @param first
	 * @param max
	 * @return
	 */
	private List<DongtanVo> _findVoByHot(int first,int max)
	{
		return dongtanDAO.findVoByHot(DongtanType.SIMPLE,first, max);
	}
	
	/**
	 * 查询最新
	 * @param first
	 * @param max
	 * @return
	 */
	private List<DongtanVo> _findVoByUpToDate(int first,int max)
	{
		return _findVoByTime(DongtanType.SIMPLE,first,max);
	}
	
	/**
	 * 根据发表时间查询
	 * @param first
	 * @param max
	 * @return
	 */
	private List<DongtanVo> _findVoByTime(int type,int first,int max)
	{
		return dongtanDAO.findVoByTime(type,first, max);
	}
	
	/**
	 * 创建
	 * @param dongtan
	 * @return
	 */
	private Dongtan _create(Dongtan dongtan,UserVo user,String ip)
	{
		dongtan.setId(_getIndex());
		dongtan.setComment_id(_getCommentIndex());
		dongtan.setComment_count(0);
		dongtan.setViews_count(0);
		dongtan.setType(DongtanType.SIMPLE);
		dongtan.setAuthor(user);
		dongtan.setIp(ip);
		dongtan.setCreate_time(DateUtil.now());
		
		pluginHelper.execute(PluginType.DONGTAN_CREATE_BEFORE, dongtan);
		dongtanDAO.create(dongtan);
		pluginHelper.execute(PluginType.DONGTAN_CREATE_AFTER, dongtan);
		
		return dongtan;
	}
	
	/**
	 * 更新浏览数
	 * @param dongtan
	 */
	private void _updateViewsCount_plus(DongtanVo dongtan)
	{
		dongtanDAO.updateViewsCount(dongtan.getId(), 1);
	}
	
	/**
	 * 更新类型
	 * @param id
	 * @param type
	 * @return
	 */
	private int _updateType(DongtanVo dongtanVo,int type)
	{
		return dongtanDAO.updateType(dongtanVo.getId(), type);
	}
	
	/**
	 * 编辑
	 * @param dongtan
	 * @return
	 */
	private int _edit(int id,String content)
	{
		Dongtan dongtan=new Dongtan();
		dongtan.setId(id);
		dongtan.setContent(content);
		return dongtanDAO.edit(dongtan);
	}
	
	/**
	 * 评论数量
	 * @param dongtan
	 */
	private void _updateCommentCount_plus(DongtanVo dongtan)
	{
		dongtanDAO.updateCommentCount(dongtan.getId(), 1);
	}
	
	/**
	 * 评论数量
	 * @param dongtan
	 */
	private void _updateCommentCount_minus(DongtanVo dongtan)
	{
		dongtanDAO.updateCommentCount(dongtan.getId(), -1);
	}
	
	private int _getCommentIndex()
	{
		return commentService._getIndex();
	}
	
	private int _getIndex()
	{
		return indexService.getMajorById(Constants.INDEX_DONGTAN);
	}
	
	private int _getToUpDateCount()
	{
		return (Integer) configService.getValueById(Config.CONFIG_2, Integer.class);
	}
	
	private int _getHotCount()
	{
		return (Integer) configService.getValueById(Config.CONFIG_3, Integer.class);
	}
	
	private int _getPageCount()
	{
		return (Integer) configService.getValueById(Config.CONFIG_4, Integer.class);
	}
	
	private void _setSimple(DongtanVo dongtanVo)
	{
		_updateType(dongtanVo,DongtanType.SIMPLE);
	}
	
	private void _setCheck(DongtanVo dongtanVo)
	{
		_updateType(dongtanVo,DongtanType.CHECK);
	}
	
	private void _setDelete(DongtanVo dongtanVo)
	{
		_updateType(dongtanVo,DongtanType.DELETE);
	}
	
	private boolean _isSimple(DongtanVo dongtanVo)
	{
		return (dongtanVo.getType().equals(DongtanType.SIMPLE));
	}
	
	private boolean _isCheck(DongtanVo dongtanVo)
	{
		return (dongtanVo.getType().equals(DongtanType.CHECK));
	}
	
	private boolean _isDelete(DongtanVo dongtanVo)
	{
		return (dongtanVo.getType().equals(DongtanType.DELETE));
	}
	
	private boolean _isAuthor(DongtanVo dongtanVo,User user)
	{
		return (dongtanVo.getAuthor().getId().equals(user.getId()));
	}
	
	/**
	 * 验证
	 * @param token 令牌
	 * @param dongtanVo 主题
	 * @param authority 主权限
	 * @param authorityOr
	 * @param authorAuthority 作者权限
	 * @param authorAuthorityOr
	 */
	private void _require(String token,DongtanVo dongtanVo,String authority[],String authorAuthority[])
	{
		_require(token,dongtanVo,authority,false,authorAuthority,false);
	}
	private void _require(String token,DongtanVo dongtanVo,String authority[],boolean authorityOr,String authorAuthority[],boolean authorAuthorityOr)
	{
		if(!security.require(authority, token, authorityOr))
		{
			User user=userService.getAuthenticationInfo(token);
			if(!_isAuthor(dongtanVo,user) || !security.require(authorAuthority, token, authorAuthorityOr))
				throw new AuthenticationException();
		}
	}
}